home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvi2ps / psdvi / psdvi.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  14KB  |  585 lines

  1. #ifndef LINT
  2. static char *rcs_header =
  3.     "$Header: psdvi.c,v 1.5 87/11/27 16:39:25 elwell Exp $";
  4. #endif
  5.  
  6. /*
  7.  * psdvi -- convert TeX DVI files to PostScript
  8.  *
  9.  * Written by Clayton M. Elwell, The Ohio State University
  10.  *
  11.  * Edit History:
  12.  *
  13.  *    $Log:    psdvi.c,v $
  14.  * Revision 1.5  87/11/27  16:39:25  elwell
  15.  * Split out PostScript prologue into separate file
  16.  * 
  17.  * Revision 1.4  87/09/17  22:13:53  elwell
  18.  * Cleaned up PostScript prologue
  19.  * 
  20.  * Revision 1.3  87/07/30  12:21:43  elwell
  21.  * Fixed bug in font scaling (TeX points vs. PostScript points)
  22.  * 
  23.  * Revision 1.2  87/07/29  11:23:02  elwell
  24.  * Added support for oblique (slanted) fonts.  The PostScript
  25.  * macro that implements this was written by L.A. Carr (as far
  26.  * as I can tell).
  27.  * 
  28.  * Revision 1.1  87/07/14  19:11:07  elwell
  29.  * Initial revision
  30.  * 
  31.  * 
  32.  */
  33.  
  34. #include <stdio.h>
  35. char *malloc();
  36. #ifdef BSD
  37. #include <pwd.h>
  38. #include <strings.h>
  39. #endif
  40.  
  41. char profile[80] = "/usr/local/lib/ps/psdvi.pro";
  42.  
  43. #define  SETC_000    0
  44. #define  SETC_127  127
  45. #define  SET1      128
  46. #define  SET2      129
  47. #define  SET3      130
  48. #define  SET4      131
  49. #define  SET_RULE  132
  50. #define  PUT1      133
  51. #define  PUT2      134
  52. #define  PUT3      135
  53. #define  PUT4      136
  54. #define  PUT_RULE  137
  55. #define  NOP       138
  56. #define  BOP       139
  57. #define  EOP       140
  58. #define  PUSH      141
  59. #define  POP       142
  60. #define  RIGHT1    143
  61. #define  RIGHT2    144
  62. #define  RIGHT3    145
  63. #define  RIGHT4    146
  64. #define  W0        147
  65. #define  W1        148
  66. #define  W2        149
  67. #define  W3        150
  68. #define  W4        151
  69. #define  X0        152
  70. #define  X1        153
  71. #define  X2        154
  72. #define  X3        155
  73. #define  X4        156
  74. #define  DOWN1     157
  75. #define  DOWN2     158
  76. #define  DOWN3     159
  77. #define  DOWN4     160
  78. #define  Y0        161
  79. #define  Y1        162
  80. #define  Y2        163
  81. #define  Y3        164
  82. #define  Y4        165
  83. #define  Z0        166
  84. #define  Z1        167
  85. #define  Z2        168
  86. #define  Z3        169
  87. #define  Z4        170
  88. #define  FONT_00   171
  89. #define  FONT_63   234
  90. #define  FNT1      235
  91. #define  FNT2      236
  92. #define  FNT3      237
  93. #define  FNT4      238
  94. #define  XXX1      239
  95. #define  XXX2      240
  96. #define  XXX3      241
  97. #define  XXX4      242
  98. #define  FNT_DEF1  243
  99. #define  FNT_DEF2  244
  100. #define  FNT_DEF3  245
  101. #define  FNT_DEF4  246
  102. #define  PRE       247
  103. #define  POST      248
  104. #define  POST_POST 249
  105.  
  106. char *program_name;
  107.  
  108. FILE *dvi_file;
  109.  
  110. open_dvi_file(s)
  111. char *s;
  112. {
  113.     dvi_file = fopen(s, "r");
  114.     if (!dvi_file) error("Unable to open DVI file %s", s);
  115. }
  116.  
  117. #define    set_dvi_file_pos(i)    fseek(dvi_file, (long) (i), 0)
  118. #define get_dvi_file_pos()    ftell(dvi_file)
  119.  
  120. get_byte()        /* get a byte from the DVI file, unsigned */
  121. {
  122.     register int i;
  123.  
  124.     if ((i = getc(dvi_file)) == EOF)
  125.     error("unexpected end of file on DVI file");
  126.     return i & 255;
  127. }
  128.  
  129. signed_byte()
  130. {
  131.     register int i;
  132.     i = get_byte();
  133.     if (i > 127) i -= 256;
  134.     return i;
  135. }
  136.  
  137. get_two_bytes()
  138. {
  139.     register int c1, c2;
  140.  
  141.     c1 = get_byte(); c2 = get_byte();
  142.     return c1 * 256 + c2;
  143. }
  144.  
  145. signed_pair()
  146. {
  147.     register int c1, c2;
  148.  
  149.     c1 = signed_byte(); c2 = get_byte();
  150.     return c1 * 256 + c2;
  151. }
  152.  
  153. get_three_bytes()
  154. {
  155.     register int c1, c2 ,c3;
  156.     c1 = get_byte(); c2 = get_byte(); c3 = get_byte();
  157.     return (c1 * 256 + c2) * 256 + c3;
  158. }
  159.  
  160. get_signed_trio()
  161. {
  162.     register int c1, c2, c3;
  163.     c1 = signed_byte(); c2 = get_byte(); c3 = get_byte();
  164.     return (c1 * 256 + c2) * 256 + c3;
  165. }
  166.  
  167. signed_quad()
  168. {
  169.     int i;
  170.     register int c1, c2, c3, c4;
  171.     c1 = signed_byte(); c2 = get_byte(); c3 = get_byte(); c4 = get_byte();
  172.     i = ((c1*256+c2)*256+c3)*256+c4;
  173.     return i;
  174. }
  175.  
  176. get_dvi_str(l, s)
  177. int l;
  178. char *s;
  179. {
  180.     int i;
  181.  
  182.     for (i = 0; i < l; i++) s[i] = get_byte();
  183.     s[i] = 0;
  184. }
  185.  
  186. include_file(s)
  187. char *s;
  188. {
  189.     FILE *fp;
  190.     int c;
  191.  
  192.     if (!(fp = fopen(s, "r"))) return -1;
  193.     while ((c = getc(fp)) != EOF) putchar(c);
  194.     fclose(fp);
  195.     return 0;
  196. }
  197.  
  198. double mag;
  199.  
  200. write_preamble_comment()
  201. {
  202.     register int byte1, byte2;
  203. #ifdef BSD
  204.     struct passwd *pw;
  205.     char h[80];
  206. #endif
  207.  
  208.     byte1 = get_byte(); byte2 = get_byte();
  209.     if (byte1 != PRE || byte2 != 2) error ("input file is not a DVI file");
  210.     set_dvi_file_pos(14);
  211.     printf("%%%%Creator: ");
  212.     byte1 = get_byte();
  213.     while (byte1--) putchar(get_byte());
  214.     putchar('\n');
  215. #ifdef BSD
  216.     pw = getpwuid(getuid());
  217.     gethostname(h, 80);
  218.     if (index(pw->pw_gecos, ','))
  219.         *(index(pw->pw_gecos, ',')) = 0;
  220.     printf("%%%%For: %s@%s (%s)\n", pw->pw_name, h, pw->pw_gecos);
  221. #endif
  222. }
  223.  
  224. scmp(s1, s2)
  225. char **s1;
  226. char **s2;
  227. {
  228.     return strcmp(*s1, *s2);
  229. }
  230.  
  231. int last_bop_pointer;
  232. double conv, true_conv, mag;
  233.  
  234. load_postamble_and_fonts()
  235. {
  236.     int pos, op, dvi_mag, numerator, denominator, max_v, max_h, max_s,
  237.     total_pages, p;
  238.     int scaled, design;
  239.     int waste, length;
  240.     char str[200];
  241.     char *ftab[500];
  242.     int nfonts, i;
  243.  
  244.     /* find postamble */
  245.  
  246.     fseek(dvi_file, -5L, 2);    /* find end of file - 5 */
  247.     pos = get_dvi_file_pos();
  248.     for (op = get_byte(); op == 223;) {
  249.     pos--; set_dvi_file_pos(pos); op = get_byte();
  250.     }
  251.  
  252.     set_dvi_file_pos(pos - 4);
  253.     pos = signed_quad();
  254.  
  255.     /* load postamble proper */
  256.  
  257.     set_dvi_file_pos(pos + 1);        /* just past the POST command */
  258.     last_bop_pointer = signed_quad();
  259.     numerator = signed_quad();
  260.     denominator = signed_quad();
  261.     dvi_mag = signed_quad();
  262.     mag = ((double) dvi_mag) / 1000.0;
  263.  
  264.     conv = (((double) numerator)/254000.0)*(72.0/((double) denominator));
  265.     true_conv = conv;
  266.     conv = true_conv * mag;
  267.  
  268.     max_v = signed_quad();
  269.     max_h = signed_quad();
  270.     max_s = get_two_bytes();
  271.  
  272.     total_pages = get_two_bytes();
  273.  
  274.     pos = get_dvi_file_pos();
  275.  
  276.     printf("%%%%DocumentFonts:");
  277.     nfonts = 0;
  278.     for (op = get_byte(); op != POST_POST; op = get_byte()) {
  279.     if (op >= FNT_DEF1 && op <= FNT_DEF4) {
  280.         p = first_par(op);
  281.         signed_quad();
  282.         scaled = signed_quad();
  283.         design = signed_quad();
  284.         waste = get_byte(); length = get_byte() + waste;
  285.         get_dvi_str(length, str);
  286.         for (i = 0; i < nfonts; i++)
  287.         if (!strcmp(str, ftab[i])) break;
  288.         if (i == nfonts) {
  289.         ftab[i] = malloc(strlen(str)+1);
  290.         strcpy(ftab[i], str);
  291.         nfonts++;
  292.         }
  293.     }
  294.     }
  295.     qsort(ftab, nfonts, sizeof(char *), scmp);
  296.     puts(ftab[0]);
  297.     for (i = 1; i < nfonts; i++) {
  298.     printf("%%%%+%s\n", ftab[i]);
  299.     free(ftab[i]);
  300.     }
  301.  
  302.     set_dvi_file_pos(pos);
  303.  
  304.     printf("%%%%Pages: %d\n%%%%EndComments\n", total_pages);
  305.  
  306.     include_file(profile);
  307.  
  308.     for (op = get_byte(); op != POST_POST; op = get_byte()) {
  309.     if (op >= FNT_DEF1 && op <= FNT_DEF4) {
  310.         p = first_par(op);
  311.         signed_quad();
  312.         scaled = signed_quad();
  313.         design = signed_quad();
  314.         waste = get_byte(); length = get_byte() + waste;
  315.         get_dvi_str(length, str);
  316.         /* notice correction factor between TeX and PostScript points */
  317.         printf("/f%d { %g /%s tf } def\n", p,
  318.            (((double)scaled)/((double)design))*mag*0.996264010, str);
  319.     }
  320.     }
  321.  
  322.     puts("%%EndProlog");
  323. }
  324.  
  325. first_par(o)
  326. int o;
  327. {
  328.     if (o >= SETC_000 && o <= SETC_127) return (o - SETC_000);
  329.     if (o >= FONT_00  && o <= FONT_63)  return (o - FONT_00);
  330.     switch (o) {
  331.     case SET1: case PUT1: case FNT1: case XXX1: case FNT_DEF1:
  332.         return get_byte();
  333.     case SET2: case PUT2: case FNT2: case XXX2: case FNT_DEF2:
  334.         return get_two_bytes();
  335.     case SET3: case PUT3: case FNT3: case XXX3: case FNT_DEF3:
  336.         return get_three_bytes();
  337.     case RIGHT1: case W1: case X1: case DOWN1: case Y1: case Z1:
  338.         return signed_byte();
  339.     case RIGHT2: case W2: case X2: case DOWN2: case Y2: case Z2:
  340.         return signed_pair();
  341.     case RIGHT3: case W3: case X3: case DOWN3: case Y3: case Z3:
  342.         return get_signed_trio();
  343.     case SET4: case SET_RULE: case PUT4: case PUT_RULE: case RIGHT4:
  344.     case W4: case X4: case DOWN4: case Y4: case Z4: case FNT4:
  345.     case XXX4: case FNT_DEF4:
  346.         return signed_quad();
  347.     case W0:
  348.         return 0;
  349.     case X0:
  350.         return 0;
  351.     case Y0:
  352.         return 0;
  353.     case Z0:
  354.         return 0;
  355.     case NOP: case BOP: case EOP: case PUSH: case POP: case PRE:
  356.     case POST: case POST_POST:
  357.     default:
  358.         return 0;
  359.     }
  360. }
  361.  
  362. char cur_name[200];
  363.  
  364. int first_bop_pointer;
  365.  
  366. find_starting_page()
  367. {
  368.     int p, found, counts_match, i;
  369.  
  370.     found = 0;
  371.     for (p = last_bop_pointer; p >= 0; p = signed_quad()) {
  372.     set_dvi_file_pos(p + 1);    /* move to byte after BOP */
  373.     /* match counts against starting page spec -- ignore for now */
  374.     for (i = 0; i < 10; i++)
  375.         signed_quad();
  376.     first_bop_pointer = p;
  377.     found = 1;
  378.     }
  379.     if (!found) error ("Starting page number could not be found");
  380. }
  381.  
  382. int cur_font;
  383.  
  384. process_pages()
  385. {
  386.     char waste_string[200];    /* string shaped waste basket */
  387.     int waste;            /* integer shaped waste basket */
  388.     int beginning_of_page, pages_processed, fonts_on_page, op, p;
  389.     int k, f, width, pxl_height, pxl_width;
  390.     int length;
  391.     int scaled_size, design_size;
  392.  
  393.     set_dvi_file_pos(first_bop_pointer);
  394.     pages_processed = 0;
  395.  
  396.     for (op = get_byte(); op != POST; op = get_byte()) {
  397.     switch (op) {
  398.         case BOP:
  399.             printf("%%%%Page: %d %d\nbop ", signed_quad(),
  400.                pages_processed+1);
  401.  
  402.         /* process one page */
  403.  
  404.         /* toss out extra counts and the back pointer */
  405.         for (k = 0; k < 10; k++) signed_quad();
  406.  
  407.         for (op = get_byte(); op != EOP; op = get_byte()) {
  408.             /* interpret one command */
  409.           nxtcmd:
  410.             if (op >= SETC_000 && op <= SETC_127) {
  411.             putchar('(');
  412.             while (op <= 128) {
  413.                 if (op == 128) {
  414.                 p = get_byte();
  415.                     printf("\\%c%c%c", p/0100 + '0',
  416.                        ((p/010) & 7) + '0', (p & 7)+'0');
  417.                 } else if (op != '\\' && op != '(' && op != ')')
  418.                 putchar(op);
  419.                 else {
  420.                 putchar('\\'); putchar(op);
  421.                 }
  422.                 op = get_byte();
  423.                 switch (op) {
  424.                 case W0:
  425.                     putchar(' '); 
  426.                     op = get_byte();
  427.                     break;
  428.                 }
  429.             }
  430.             puts(")s");
  431.             goto nxtcmd;
  432.             } else if ((op >= FONT_00 && op <= FONT_63) ||
  433.                    (op >= FNT1 && op <= FNT4)) {
  434.             p = first_par(op);
  435.             printf("f%d ", p);
  436.             } else {
  437.             p = first_par(op);    /* get first parameter */
  438.             switch (op) {
  439.                 case SET1: case SET2: case SET3: case SET4:
  440.                     printf("(\\%c%c%c)s ", p/0100 + '0',
  441.                        ((p/010) & 7) + '0', (p & 7)+'0');
  442.                 break;
  443.                 case PUT1: case PUT2: case PUT3: case PUT4:
  444.                     printf("(\\%c%c%c)p ", p/0100 + '0',
  445.                        ((p/010) & 7) + '0', (p & 7)+'0');
  446.                 break;
  447.                 case SET_RULE:
  448.                 /* output rule and move, height in p */
  449.                 width = signed_quad();
  450.                 printf("%g %g rl\n", conv*(double)width,
  451.                        conv*(double)p);
  452.                 break;
  453.                 case PUT_RULE:
  454.                 /* output rule, height in p */
  455.                 width = signed_quad();
  456.                 printf("%g %g pr\n", conv*(double)width,
  457.                        conv*(double)p);
  458.                 break;
  459.                 case NOP:
  460.                 break;
  461.                 case PUSH:
  462.                 printf("S ");
  463.                 break;
  464.                 case POP:
  465.                 printf("R ");
  466.                 break;
  467.                 case X0: 
  468.                 printf("x0 ");
  469.                                 break;
  470.                 case X1: case X2: case X3: case X4:
  471.                 printf("%g xs ", conv*(double)p);
  472.                 break;
  473.                 case W0:
  474.                 printf("w0 ");
  475.                 break;
  476.                 case W1: case W2: case W3: case W4:
  477.                 printf("%g ws ", conv*(double)p);
  478.                     break;
  479.                 case RIGHT1: case RIGHT2:
  480.                 case RIGHT3: case RIGHT4:
  481.                 printf("%g r ", conv*(double)p);
  482.                 break;
  483.                 case Z0:
  484.                 printf("z0 ");
  485.                 break;
  486.                 case Z1: case Z2: case Z3: case Z4:
  487.                 printf("%g zs ", conv*(double)p);
  488.                 break;
  489.                 case Y0:
  490.                 printf("y0 "); break;
  491.                 case Y1: case Y2: case Y3: case Y4:
  492.                 printf("%g ys ", conv*(double)p); break;
  493.                 case DOWN1: case DOWN2: case DOWN3: case DOWN4:
  494.                 printf("%g d ", conv*(double)p);
  495.                 break;
  496.                 case FNT_DEF1: case FNT_DEF2:
  497.                 case FNT_DEF3: case FNT_DEF4:
  498.                 signed_quad();
  499.                 scaled_size = signed_quad();
  500.                 design_size = signed_quad();
  501.                 waste = get_byte(); length = get_byte()+waste;
  502.                 get_dvi_str(length, waste_string);
  503. /*                printf("/f%d { %g /%s tf } def\n", p,
  504.                        ((double)scaled_size)/
  505.                        ((double)design_size),
  506.                        waste_string);        */
  507.                 break;
  508.                 case XXX1: case XXX2: case XXX3: case XXX4:
  509.                 get_dvi_str(p, waste_string);
  510.                 do_special(waste_string);
  511.                 break;
  512.                 default:
  513.                 error("Unknown or misplaced DVI command: %d",
  514.                     op);
  515.                 break;
  516.             }
  517.             }
  518.         }
  519.  
  520.         puts("eop");            /* page separator */
  521.         pages_processed++;
  522.         break;
  523.         case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
  524.         p = first_par(op);        /* skip external font no. */
  525.         signed_quad();
  526.         scaled_size = signed_quad();
  527.         design_size = signed_quad();
  528.         waste = get_byte(); length = get_byte()+waste;
  529.         get_dvi_str(length, waste_string);
  530. /*        printf("/f%d { %g /%s tf } def\n", p,
  531.                ((double)scaled_size)/
  532.                ((double)design_size),
  533.                waste_string);        */
  534.         break;
  535.     }
  536.     }
  537.     puts("%%Trailer");
  538. }
  539.  
  540. main(argc, argv)
  541. int argc;
  542. char **argv;
  543. {
  544.     int i;
  545.  
  546.     program_name = argv[0];
  547.     if (argc != 2) {
  548.     fprintf(stderr, "usage: %s dvi-file\n", argv[0]);
  549.     exit(-1);
  550.     }
  551.  
  552.     printf("%%!PS-Adobe-1.0\n%%%%Title: %s\n", argv[1]);
  553.     open_dvi_file(argv[1]);
  554.     write_preamble_comment();
  555.     load_postamble_and_fonts();
  556.     find_starting_page();
  557.     process_pages();
  558. }
  559.  
  560. error(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  561. char *s;
  562. int a1, a2, a3, a4, a5, a6, a7, a8, a9;
  563. {
  564.     fprintf(stderr, "%s: ", program_name);
  565.     fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  566.     putc('\n', stderr);
  567.     exit(-1);
  568. }
  569.  
  570. do_special(s)
  571. char *s;
  572. {
  573.     FILE *fp;
  574.     int c;
  575.  
  576.     if (s[0] != '!') { puts(s); return; }
  577.     if (!strncmp(s, "!include", 8)) {
  578.     if (include_file(s+9)) {
  579.         fprintf(stderr, "%s: WARNING: cannot include file %s\n",
  580.             program_name, s+9);
  581.         return;
  582.     }
  583.     } else puts(s);
  584. }
  585.